#include "tdp2_liveresource.hpp"
#include "tdp2_renderdevice.hpp"

namespace TDP
{
	namespace Resources
	{
		LiveCompiledShaderResource::LiveCompiledShaderResource(Rendering::IRenderDevice *device, const RDX::ObjectManagement::Allocator &alloc, ShaderSpec::ShaderType st, LargeUInt sizeBytes)
		{
			_device = device;
			_alloc = alloc;
			_shaderType = st;
			_preloadBuffer = NULL;
			_bytesTotal = sizeBytes;
			_bytesLoaded = 0;
			_isCommitted = false;
			_rsh = 0;
		}

		LiveCompiledShaderResource::~LiveCompiledShaderResource()
		{
			if(_rsh != 0)
				_device->DestroyShader(_rsh);
			_rsh = 0;
			if(_preloadBuffer != NULL)
				_alloc.Free(_preloadBuffer);
			_preloadBuffer = NULL;
		}

		bool LiveCompiledShaderResource::IsUploaded() const
		{
			return _isCommitted;
		}

		bool LiveCompiledShaderResource::DigestStreamData(const void *data, LargeUInt numBytesAvailable, LargeUInt *outNumDigested)
		{
			*outNumDigested = 0;
			if(!numBytesAvailable)
				return true;

			LargeUInt loadAmount = _bytesTotal - _bytesLoaded;
			if(loadAmount > numBytesAvailable)
				loadAmount = numBytesAvailable;

			if(_preloadBuffer != NULL)
			{
				void *insertionPoint = static_cast<void *>(static_cast<UInt8 *>(_preloadBuffer) + _bytesLoaded);
				memcpy(insertionPoint, data, loadAmount);
			}
			_bytesLoaded += loadAmount;
			*outNumDigested = loadAmount;

			if(_bytesLoaded == _bytesTotal)
			{
				if(_preloadBuffer != NULL)
				{
					_isCommitted = _device->CreateShader(_shaderType, _preloadBuffer, _bytesTotal, &_rsh);
					_alloc.Free(_preloadBuffer);
				}
				return false;
			}
			// More to go
			return true;
		}

		void LiveCompiledShaderResource::StartStreaming()
		{
			_bytesLoaded = 0;
			_preloadBuffer = _alloc.CAlloc<UInt8>(_bytesTotal);
		}
	}
}
